package com.rs;

import java.util.concurrent.TimeUnit;

import org.jboss.netty.channel.ChannelException;

import com.rs.game.npc.NpcDefinition;
import com.rs.cache.Cache;
import com.rs.cache.loaders.ItemDefinitions;
import com.rs.cache.loaders.ItemEquipIds;
import com.rs.cache.loaders.NPCDefinitions;
import com.rs.cache.loaders.ObjectDefinitions;
import com.rs.cores.CoresManager;
import com.rs.game.Region;
import com.rs.game.RegionBuilder;
import com.rs.game.World;
import com.rs.game.player.Player;
import com.rs.game.player.controlers.ControlerHandler;
import com.rs.game.player.dialogues.DialogueHandler;
import com.rs.net.ServerChannelHandler;
import com.rs.utils.ItemBonuses;
import com.rs.utils.Logger;
import com.rs.utils.MapAreas;
import com.rs.utils.MapContainersXteas;
import com.rs.utils.NPCSpawns;
import com.rs.utils.ObjectSpawns;
import com.rs.utils.SerializableFilesManager;
import com.rs.utils.huffman.Huffman;
public final class Launcher {
	
	public static final void main(String[] args) throws Exception {
		long currentTime = System.currentTimeMillis();
		Logger.log("Launcher", "Initing Cache..."); 
		Cache.init();
		ItemEquipIds.init();
		Huffman.init();
		Logger.log("Launcher", "Initing Data Files..."); 
		MapContainersXteas.init();
		MapAreas.init();
		ObjectSpawns.init();
		NPCSpawns.init();
		ItemBonuses.init();
		Logger.log("Launcher", "Initing Dialogues..."); 
		DialogueHandler.init();
		Logger.log("Launcher", "Initing Controlers..."); 
		ControlerHandler.init();
		Logger.log("Launcher", "Initing Cores Manager...");
		CoresManager.init();
		Logger.log("Launcher", "Initing World...");
		World.init();
		Logger.log("Launcher", "Initing Region Builder..."); 
		RegionBuilder.init();
		Logger.log("Launcher", "Initing Server Channel Handler...");
		try {
			ServerChannelHandler.init();
		}catch(ChannelException e) {
			e.printStackTrace();
			Logger.log("Launcher", "Failed initing Server Channel Handler. Shutting down...");
			shutdown();
			return;
		}
		Logger.log("Launcher", "Server took "+(System.currentTimeMillis()-currentTime)+" milli seconds to launch.");
		addCleanMemoryTask();
		addAccountsSavingTask();
	}
	
	private static final void addCleanMemoryTask() {
		CoresManager.slowExecutor.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				if(Runtime.getRuntime().freeMemory() < Settings.MIN_FREE_MEM_ALLOWED) 
					cleanMemory();
			}
		}, 0, 10, TimeUnit.MINUTES);
	}
	
	private static final void addAccountsSavingTask() {
		CoresManager.slowExecutor.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				saveAccounts();
				
			}
		}, 0, 15, TimeUnit.MINUTES);
	}
	
	public static final void saveAccounts() {
		for(Player player : World.getPlayers()) {
			if(player == null || !player.hasStarted() || player.hasFinished())
				continue;
			SerializableFilesManager.savePlayer(player);
		}
	}
	
	public static final void cleanMemory() {
		ItemDefinitions.clearItemsDefinitions();
		NPCDefinitions.clearNPCDefinitions();
		ObjectDefinitions.clearObjectDefinitions();
		for(Region region : World.getRegions().values())
			region.removeMapFromMemory();
		System.gc();
	}
	
	public static final void shutdown() {
		try {
			ServerChannelHandler.shutdown();
			CoresManager.shutdown();
		} finally {
			System.exit(0);
		}
	}
	
	public static final void restart() {
		//TODO
	}
	
	private Launcher() {
		
	}
	
	
}
